home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / SCC.C < prev    next >
C/C++ Source or Header  |  1990-08-15  |  53KB  |  1,797 lines

  1. /*
  2.  * Generic driver for Z8530 SCC chip in SLIP, KISS or AX.25 mode.
  3.  *
  4.  * Written by R.E. Janssen (PE1CHL) using material from earlier
  5.  * EAGLE and PC100 drivers in this package.
  6.  *
  7.  * The driver has initially been written for my own Atari SCC interface
  8.  * board, but it could eventually replace the other SCC drivers.
  9.  *
  10.  * Unfortunately, there is little consistency between the different interface
  11.  * boards, as to the use of a clock source, the solution for the fullduplex
  12.  * clocking problem, and most important of all: the generation of the INTACK
  13.  * signal.  Most designs do not even support the generation of an INTACK and
  14.  * the read of the interrupt vector provided by the chip.
  15.  * This results in lots of configuration parameters, and a fuzzy
  16.  * polltable to be able to support multiple chips connected at one interrupt
  17.  * line...
  18.  *
  19.  * when the constant SCC_HWTIMER is defined during compilation of SCC.C,
  20.  * we'll install the timer directly on the timer hardware interrupt, not on the
  21.  * timer-tick user-exit (int 1c) because some programs take over that one
  22.  * without saving and calling the original handler installed there...
  23.  *
  24.  */
  25.  
  26. #define SCC_HWTIMER            /* timer tick on hardware interrupt */
  27.  
  28. #ifdef ATARI_ST
  29. # ifdef MWC
  30. #  include <osbind.h>
  31. # endif
  32. # ifdef __TURBOC__
  33. #  include <tos.h>
  34. # endif
  35. #endif
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #include <time.h>
  40. #include "global.h"
  41. #include "mbuf.h"
  42. #include "buffers.h"
  43. #include "iface.h"
  44. #include "slip.h"
  45. #include "scc.h"
  46. #include "8530.h"
  47. #include "8536.h"
  48. #include "ax25.h"
  49. #include "trace.h"
  50.  
  51. /* variables used by the SCC interrupt handler in sccvec.s */
  52.  
  53. #ifdef ATARI_ST
  54. ioaddr sccgpiploc;            /* location of MFP GPIP register */
  55. int    sccgpipbit;            /* bit# to test in MFP GPIP reg */
  56. ioaddr sccisrloc;            /* location of MFP ISR */
  57. int    sccisrbit;            /* bit# to clear in MFP ISR */
  58. extern void (*sccotvec)();        /* location to store old int vec */
  59.  
  60. struct sccinfo sccinfo;            /* global info about SCCs */
  61. struct sccchan *sccchan[2 * MAXSCC];    /* information per channel */
  62. ioaddr sccvecloc;            /* location to access for SCC vector */
  63. unsigned char sccmaxvec;        /* maximum legal vector from SCC */
  64. ioaddr sccpolltab[MAXSCC+1][2];        /* polling table when no vectoring */
  65. #endif
  66.  
  67. #ifdef MSDOS
  68. static void (*orgivec)();        /* original interrupt vector */
  69. extern void (*far sccotvec)();        /* location to store old int vec */
  70.  
  71. struct sccinfo sccinfo = {0};        /* global info about SCCs */
  72. struct sccchan *sccchan[2 * MAXSCC] = {0}; /* information per channel */
  73. ioaddr sccvecloc = {0};            /* location to access for SCC vector */
  74. unsigned char sccmaxvec = {0};        /* maximum legal vector from SCC */
  75. ioaddr sccpolltab[MAXSCC+1][2] = {0};    /* polling table when no vectoring */
  76.  
  77. # if ((defined(MSC) && defined(INLINE)) || (defined(__TURBOC__) && defined(inportb)))
  78. static unsigned scc_delay (v)        /* delay for about 5 PCLK cycles */
  79.    unsigned v;                /* pass-through used for input */
  80.  
  81. {
  82.    return v;                /* return the passed parameter */
  83. }
  84. # endif
  85. #endif
  86.  
  87. unsigned char random = 0;        /* random number for p-persist */
  88.  
  89. extern char nospace[];
  90.  
  91. static int scc_stop(),scc_raw(),scc_slipraw(),doscc();
  92. static void scc_async(),scc_sdlc(),scc_recv();
  93. static void scc_tossb(),scc_txon(),scc_txoff();
  94. static int scc_ax25(),scc_aioctl(),scc_sioctl();
  95. static unsigned int scc_speed();
  96.  
  97. /* Attach an SCC channel to the system, or initialize SCC driver.
  98.  * operation depends on argv[2]:
  99.  * when "init", the SCC driver is initialized, and global information about
  100.  * the hardware is set up.
  101.  * argv[0]: hardware type, must be "scc"
  102.  * argv[1]: number of SCC chips we will support
  103.  * argv[2]: mode, must be: "init" in this case
  104.  * argv[3]: base address of SCC chip #0 (hex)
  105.  * argv[4]: spacing between SCC chip base addresses
  106.  * argv[5]: offset from chip base address to channel A control register
  107.  * argv[6]: offset from chip base address to channel B control register
  108.  * argv[7]: offset from each channel's control register to data register
  109.  * argv[8]: address of INTACK/Read Vector port. 0 to read from RR3A/RR2B
  110.  * argv[9]: CPU interrupt vector number for all connected SCCs
  111.  * argv[10]: clock frequency (PCLK/RTxC) of all SCCs in cycles per second
  112.  *         prefix with "p" for PCLK, "r" for RTxC clock (for baudrate gen)
  113.  * argv[11]: optional hardware type (for special features)
  114.  * argv[12]: optional extra parameter for special hardware
  115.  *
  116.  * otherwise, a single channel is attached using the specified parameters:
  117.  * argv[0]: hardware type, must be "scc"
  118.  * argv[1]: SCC channel number to attach, 0/1 for first chip A/B, 2/3 for 2nd...
  119.  * argv[2]: mode, can be:
  120.  *        "slip", "kiss", "ax25"
  121.  * argv[3]: interface label, e.g., "sl0"
  122.  * argv[4]: maximum transmission unit, bytes
  123.  * argv[5]: interface speed, e.g, "1200". prefix with "d" when an external
  124.  *        divider is available to generate the TX clock.  When the clock
  125.  *        source is PCLK, this can be a /32 divider between TRxC and RTxC.
  126.  *        When the clock is at RTxC, the TX rate must be supplied at TRxC.
  127.  *        This is needed only for AX.25 fullduplex.
  128.  *        When this arg is given as "ext", the transmit and receive clock
  129.  *        are external, and the BRG and DPLL are not used.
  130.  * argv[6]: callsign used on the radio channels
  131.  */
  132.  
  133. int
  134. scc_attach(argc,argv)
  135. int argc;
  136. char *argv[];
  137. {
  138.     register struct interface *ifp;
  139.     struct sccchan *scc;
  140.     unsigned int chan,brgrate;
  141.     int pclk = 0;
  142.     char *p;
  143.     char r11;
  144.     int hwtype = 0,hwparam = 0;
  145. #ifdef ATARI_ST
  146.     long save_ssp;
  147. #endif
  148.     extern struct interface *ifaces;
  149.     int slip_send(),kiss_ioctl(),kiss_raw();
  150.     void kiss_recv(),slip_recv();
  151.     long atol(),htol();
  152.  
  153.     /* first handle the special "init" mode, to initialize global stuff */
  154.  
  155.     if(!strcmp(argv[2],"init")){
  156.     if(argc < 11)            /* need at least argv[1]..argv[10] */
  157.         return -1;
  158.  
  159.     if (isupper(argv[10][0]))
  160.         argv[10][0] = tolower(argv[10][0]);
  161.  
  162.     if (argv[10][0] == 'p'){    /* wants to use PCLK as clock? */
  163.         pclk = 1;
  164.         argv[10]++;
  165.     } else {
  166.         if (argv[10][0] == 'r')    /* wants to use RTxC? */
  167.         argv[10]++;        /* that's the default */
  168.     }
  169.  
  170.     if (argc > 11)            /* optional hardware type */
  171.         hwtype = htoi(argv[11]);    /* it is given in hex */
  172.  
  173.     if (argc > 12)            /* optional hardware param */
  174.         hwparam = htoi(argv[12]);    /* also in hex */
  175.  
  176.     return scc_init(atoi(argv[1]),(ioaddr) htol(argv[3]),atoi(argv[4]),
  177.             atoi(argv[5]),atoi(argv[6]),atoi(argv[7]),
  178.             (ioaddr) htol(argv[8]),atoi(argv[9]),
  179.             atol(argv[10]),pclk,hwtype,hwparam);
  180.     }
  181.  
  182.     /* not "init", so it must be a valid mode to attach a channel */
  183.  
  184.     if (strcmp(argv[2],"ax25") && strcmp(argv[2],"kiss") &&
  185.     strcmp(argv[2],"slip")){
  186.     printf("Mode %s unknown for SCC\n",argv[2]);
  187.     return -1;
  188.     }
  189.  
  190.     if (!sccinfo.init){
  191.     printf("First init SCC driver\n");
  192.     return -1;
  193.     }
  194.  
  195.     if ((chan = atoi(argv[1])) > sccinfo.maxchan){
  196.     printf("SCC channel %d out of range\n",chan);
  197.     return -1;
  198.     }
  199.  
  200.     if (sccchan[chan] != NULLCHAN){
  201.     printf("SCC channel %d already attached\n",chan);
  202.     return -1;
  203.     }
  204.  
  205.     /* create interface structure and fill in details */
  206.  
  207.     if ((ifp = (struct interface *) calloc(1,sizeof(struct interface))) == NULLIF){
  208.     printf(nospace);
  209.     return -1;
  210.     }
  211.  
  212.     if ((ifp->name = malloc(strlen(argv[3]) + 1)) == NULLCHAR){
  213.     printf(nospace);
  214.     free(ifp);
  215.     return -1;
  216.     }
  217.     strcpy(ifp->name,argv[3]);
  218.  
  219.     ifp->mtu = atoi(argv[4]);
  220.     ifp->dev = chan;
  221.     ifp->recv = doscc;
  222.     ifp->stop = scc_stop;
  223.  
  224.     if ((scc = (struct sccchan *) calloc(1,sizeof(struct sccchan))) == NULLCHAN){
  225.     printf(nospace);
  226.     free(ifp->name);
  227.     free(ifp);
  228.     return -1;
  229.     }
  230.  
  231.     scc->ctrl = sccinfo.iobase + (chan / 2) * sccinfo.space + sccinfo.off[chan % 2];
  232.     scc->data = scc->ctrl + sccinfo.doff;
  233.     scc->iface = ifp;
  234.  
  235.     sccchan[chan] = scc;        /* put addr in table for interrupts */
  236.  
  237.     switch (argv[2][0])            /* mode already checked above */
  238.     {
  239.     case 'a':                /* AX.25 */
  240.     /* default: RXclk DPLL, TXclk BRG. BRG reprogrammed